﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using intelliEssay.Core;
using DocumentFormat.OpenXml.Wordprocessing;
using intelliEssay.Core.DocumentStructure;
using intelliEssay.Interop;
using intelliEssay.Interop.ParagraphStyle;

namespace intelliEssay.Checkers.TitleChecker
{
    public class TitleChecker : IEssayChecker
    {
        public void Run(Core.Task task)
        {
            var metaList = task.documentStructure.LviParagraph;
            SequenceTest(task, metaList);



            for (int level = 1; level < metaList.Length; level++)
            {
                Paragraph standardParagraph = StandardFormats.GetStandardFormatByDocumentPart(Core.DocumentStructure.DocumentParts.LviParagraph, level, task);
                StandardRunInfoEx standardRunInfo = new StandardRunInfoEx(task.TaskObjectRoot, standardParagraph.Elements<Run>().First(), task.taskSetting.hostApp);
                for (int pidx = 0; pidx < metaList[level].Count; pidx++)
                {
                    var runs = metaList[level][pidx].Elements<Run>().ToArray();
                    for (int ridx = 0; ridx < runs.Length; ridx++)
                    {
                        RunInfoEx runInfo = new RunInfoEx(task.TaskObjectRoot, runs[ridx], task.taskSetting.hostApp);
                        List<string> unmatchedAttributes = new List<string>();
                        if (!standardRunInfo.SemanticEqual(runInfo, out unmatchedAttributes))
                        {
                            foreach (var attribute in unmatchedAttributes)
                            {
                                task.AddEssayExceptionToEssayExceptionCollection(new EssayException(ExceptionType.Font, attribute + "的设置错误，应当为" + standardRunInfo.GetSemanticValue(attribute), runs[ridx], task, true));
                            }
                        }
                    }
                }
            }
            for (int level = 1; level < metaList.Length; level++)
            {
                if (task.documentStructure.LviParagraph[level].Count != 0)
                {
                    string defaultLvlText = "";
                    NumberFormatValues defaultNumFmtvalue = NumberFormatValues.None;
                    if (!TryGetLvlTextAndFormatValues(task.documentStructure.ParagraphNumbering, metaList[level][0], out defaultLvlText, out defaultNumFmtvalue))
                    {
                        task.AddEssayExceptionToEssayExceptionCollection(new EssayException(ExceptionType.Numbering, level + "标题未标号或使用手动标号", task.documentStructure.LviParagraph[level][0], task, false));
                        continue;
                    }
                    for (int pIdx = 0; pIdx < metaList[level].Count; pIdx++)
                    {
                        string currentLvlText = "";
                        NumberFormatValues currentNumFmtValue = NumberFormatValues.None;
                        if (metaList[level][pIdx].InnerText == "绪论")
                        {
                        }
                        bool currentSuccess = TryGetLvlTextAndFormatValues(task.documentStructure.ParagraphNumbering, metaList[level][pIdx], out currentLvlText, out currentNumFmtValue);
                        if (!currentSuccess)
                        {
                            task.AddEssayExceptionToEssayExceptionCollection(new EssayException(ExceptionType.Numbering, level + "标题未标号或使用手动标号", task.documentStructure.LviParagraph[level][0], task, false));
                        }
                        if (currentLvlText != defaultLvlText)
                        {
                            task.AddEssayExceptionToEssayExceptionCollection(new EssayException(ExceptionType.Numbering, level + "级标题标号格式不统一", task.documentStructure.LviParagraph[level][0], task, true));
                            defaultLvlText = currentLvlText;
                        }
                        if (currentNumFmtValue != defaultNumFmtvalue)
                        {
                            task.AddEssayExceptionToEssayExceptionCollection(new EssayException(ExceptionType.Numbering, level + "级标题标号的符号不统一", task.documentStructure.LviParagraph[level][0], task, true));
                            defaultNumFmtvalue = currentNumFmtValue;
                        }
                    }
                }
            }


        }

        private void SequenceTest(Core.Task task, List<Paragraph>[] metaList)
        {
            for (int i = 0; i <= metaList.Length; i++)
            {
                LevelIndexDictionary[i + 1] = 0;
            }
            for (int idx = 0; idx < metaList[0].Count; idx++)
            {
                try
                {
                    string exception;
                    if (metaList[0][idx].InnerText.Contains("（1）ALL—AML数据集"))
                    {
                    }
                    if (!TitleNumberingInRange(task.documentStructure.ParagraphNumbering.ParagraphNumberingLevel[metaList[0][idx]], task.documentStructure.ParagraphNumbering.ParagraphNumberingDecimalFmt[metaList[0][idx]], task.documentStructure.ParagraphNumbering.ParagraphNumberingLevelText[metaList[0][idx]], out exception))
                    {
                        task.AddEssayExceptionToEssayExceptionCollection(new EssayException(ExceptionType.Numbering, exception, metaList[0][idx], task, true));
                    }
                }
                catch (KeyNotFoundException)
                {

                }
            }
        }

        bool TitleNumberingInRange(int lvl, string numberingTxt, string lvlText, out string exception)
        {
            exception = "";
            bool detectedError = false;
            if (lastReadLevel == -1)
            {
                if (lvl != 1 || numberingTxt != "1.")
                {
                    exception = "标题从1开始标号";
                    detectedError = true;
                }
                lastReadLevel = lvl;
            }
            if ((lvl > lastReadLevel && lvl != lastReadLevel + 1) && lastReadLevel != lvl && detectedError == false)
            {
                exception = "在开始" + lvl + "级标题前，必须开始" + (lastReadLevel + 1) + "级标题";
                detectedError = true;
            }
            if (lastReadLevel > lvl)
            {
                for (int i = lvl + 1; i <= lastReadLevel; i++)
                {
                    LevelIndexDictionary[i] = 0;
                }
            }
            LevelIndexDictionary[lvl]++;
            if (BuildCorrectNumberingTxt(lvl) != numberingTxt && detectedError == false)
            {
                //Used another numbering system.eg, 3.1.1 then (1)
                if (lvlText.Split('%').Length == 2)
                {
                    if (LevelIndexDictionary[lvl] + "." != numberingTxt)
                    {
                        exception = "标号错误";
                        detectedError = true;
                    }
                }
                else
                {
                    exception = "标号错误";
                    detectedError = true;
                }
            }
            lastReadLevelText = lvlText;
            lastReadLevel = lvl;
            return !detectedError;
        }
        int lastReadLevel = -1;
        string lastReadLevelText;
        Dictionary<int, int> LevelIndexDictionary = new Dictionary<int, int>();
        string BuildCorrectNumberingTxt(int lvl)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 1; i <= lvl; i++)
            {
                sb.Append(LevelIndexDictionary[i] + ".");
            }
            return sb.ToString();
        }
        bool TryGetLvlTextAndFormatValues(ParagraphNumbering paraNumbering, Paragraph para, out string lvlText, out NumberFormatValues numFmtValue)
        {
            lvlText = "";
            numFmtValue = NumberFormatValues.None;
            try
            {
                lvlText = paraNumbering.GetParagraphLevelText(para);
                numFmtValue = paraNumbering.GetParagraphFormatValue(para);
                return true;
            }
            catch (ApplicationException)
            {
                return false;
            }
        }

        public void Cancel(Core.Task task)
        {
            throw new NotImplementedException();
        }

        public string GetDescription(string cultureInfo)
        {
            return "Checks title leveling and formatting";
        }

        public string GetName(string cultureInfo)
        {
            return "Title Checker";
        }
    }
}
